#include "client.h"
#include "str_util.h"

int tcpConnect(const char * ip, unsigned short port)
{
    //1. 创建TCP的客户端套接字
    int clientfd = socket(AF_INET, SOCK_STREAM, 0);
    if(clientfd < 0) {
        perror("socket");
        return -1;
    }

    //2. 指定服务器的网络地址
    struct sockaddr_in serveraddr;
    //初始化操作,防止内部有脏数据
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;//指定IPv4
    serveraddr.sin_port = htons(port);//指定端口号
    //指定IP地址
    serveraddr.sin_addr.s_addr = inet_addr(ip);

    //3. 发起建立连接的请求
    int ret = connect(clientfd, (const struct sockaddr*)&serveraddr, sizeof(serveraddr));
    if(ret < 0) {
        perror("connect");
        close(clientfd);
        return -1;
    }
    return clientfd;
}


//其作用：确定接收len字节的数据
int recvn(int sockfd, void * buff, int len)
{
    int left = len;//还剩下多少个字节需要接收
    char * pbuf = buff;
    int ret = -1;
    while(left > 0) {
        ret = recv(sockfd, pbuf, left, 0);
        if(ret == 0) {
            break;
        } else if(ret < 0) {
            perror("recv");
            return -1;
        }

        left -= ret;
        pbuf += ret;
    }
    //当退出while循环时，left的值等于0
    return len - left;
}

//作用: 确定发送len字节的数据
int sendn(int sockfd, const void * buff, int len)
{
    int left = len;
    const char * pbuf = buff;
    int ret = -1;
    while(left > 0) {
        ret = send(sockfd, pbuf, left, 0);
        if(ret < 0) {
            perror("send");
            return -1;
        }

        left -= ret;
        pbuf += ret;
    }
    return len - left;
}

//解析命令
int parseCommand(const char * pinput, int len, train_t * pt)
{
    char *pstrs[10] = {0};
    int cnt = 0;
    splitString(pinput, pstrs, 10, &cnt);
    pt->type = getCommandType(pstrs[0]);

    pt->len = 0; // 初始化长度
    char *temp = pt->buff;
    int j = 1;

    while (cnt > 1 && j < cnt) { // 命令格式允许多个参数，每个参数中间用空格隔离
        int paramLen = strlen(pstrs[j]);
        strncpy(temp, pstrs[j], paramLen);
        temp += paramLen;
        *temp = ' ';
        temp++;
        pt->len += paramLen + 1;
        j++;
    }

    if (pt->len > 0) {
        pt->len--; // 删除最后一个空格
        *(temp - 1) = '\0'; // 替换最后一个空格为字符串结束符
    } else {
        pt->buff[0] = '\0'; // 如果没有参数，确保buff以字符串结束符结尾
    }

    freeStrs(pstrs, cnt);
    return 0;
}




//------------------------------------------------------
//第一期
/*
int recvfile(int sockfd) {
    int nready;

    // 1. 接收文件名长度
    int filename_len;
    nready = recvn(sockfd, &filename_len, sizeof(filename_len));
    if (nready != sizeof(filename_len)) {
        perror("recv filename length failed");
        return -1;
    }

    // 2. 接收文件名
    char *filename = (char *)malloc(filename_len + 1);
    if (filename == NULL) {
        perror("malloc");
        return -1;
    }
    nready = recvn(sockfd, filename, filename_len);
    if (nready != filename_len) {
        perror("recv filename failed");
        free(filename);
        return -1;
    }
    filename[filename_len] = '\0';
    printf("Filename: %s\n", filename);

    // 3. 接收文件大小
    off_t file_size;
    nready = recvn(sockfd, &file_size, sizeof(file_size));
    if (nready != sizeof(file_size)) {
        perror("recv file size failed");
        free(filename);
        return -1;
    }
    printf("File size: %ld\n", file_size);

    // **** 断点续传 ****
    // 获取已接收文件大小
    off_t received_size = 0;
    struct stat fileStat;
    if (stat(filename, &fileStat) == 0) {
        received_size = fileStat.st_size;
    }
    printf("File already received: %ld bytes\n", received_size);

    // 检查已接收的大小是否超过实际文件大小，如果超过，删除这个文件并重新下载
    if (received_size > file_size) {
        printf("Local file is larger than server file, removing local file and restarting download...\n");
        remove(filename);
        received_size = 0; // 重置收到的大小
    }

    // 发送已接收文件大小
    send(sockfd, &received_size, sizeof(received_size), 0);
    // **** 断点续传结束 ****

    // 4. 打开文件
    int fd = open(filename, O_WRONLY | O_CREAT, 0644);
    if (fd == -1) {
        perror("open file failed");
        free(filename);
        return -1;
    }

    // 5. 定位文件指针到已接收数据之后
    if (lseek(fd, received_size, SEEK_SET) == -1) {
        perror("lseek failed");
        close(fd);
        free(filename);
        return -1;
    }

    // 6. 接收文件内容并写入文件
    char buffer[4096]; // 使用缓冲区提高效率
    off_t remaining_size = file_size - received_size;
    while (remaining_size > 0) {
        size_t to_read = (remaining_size < (long)sizeof(buffer)) ? remaining_size : sizeof(buffer);
        nready = recvn(sockfd, buffer, to_read);
        if (nready <= 0) {
            perror("recv file content failed");
            close(fd);
            free(filename);
            return -1;
        }
        printf("recv bytes: %d\n", nready);

        // 写入数据到文件
        ssize_t nwrite = write(fd, buffer, nready);
        if (nwrite != nready) {
            perror("write to file failed");
            close(fd);
            free(filename);
            return -1;
        }
        remaining_size -= nready;
    }

    // 7. 清理资源
    close(fd);
    free(filename);
    printf("File received successfully.\n");
    return 0;
}
*/
//第一期
//-----------------------------------------------------------
int getCommandType(const char * str)
{
    if(!strcmp(str, "pwd")) 
        return CMD_TYPE_PWD;
    else if(!strcmp(str, "ls"))
        return CMD_TYPE_LS;
    else if(!strcmp(str, "cd"))
        return CMD_TYPE_CD;
    else if(!strcmp(str, "mkdir"))
        return CMD_TYPE_MKDIR;
    else if(!strcmp(str,"rmdir"))
        return CMD_TYPE_RMDIR;
    else if(!strcmp(str,"puts"))
        return CMD_TYPE_PUTS;
    else if(!strcmp(str,"gets"))
        return CMD_TYPE_GETS;
    else
        return CMD_TYPE_NOTCMD;
}


//----------------------------------------------------------------------
//第一期
/*
void Sendfile(int sockfd, const char *filename) {
    FILE *fp = fopen(filename, "rb");
    if (!fp) {
        perror("打开文件失败");
        return;
    }

    // 获取文件大小
    fseek(fp, 0, SEEK_END);
    int file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    // 发送文件大小
    int ret = send(sockfd, &file_size, sizeof(file_size), 0);
    if (ret <= 0) {
        perror("发送文件大小失败");
        fclose(fp);
        return;
    }
    printf("发送文件大小: %d\n", file_size);

    // 发送文件数据
    char buffer[1024];
    int read_size;
    while ((read_size = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
        ret = send(sockfd, buffer, read_size, 0);
        if (ret <= 0) {
            perror("发送文件数据失败");
            break;
        }
    }

    // 关闭文件
    fclose(fp);
    printf("文件发送完成。\n");
}

*/
//第一期
//-------------------------------------------------------------------
